package tdomhan.addict.dictionary;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

import tdomhan.addict.parser.Translation;

/**
 * creates two stardict dictionaries from two sorted lists of translations, that will
 * be provided by a object of the Dictionary class.
 * @author tobi
 *
 */
public class StardictFileCreator {
	
	private Dictionary dic;
	
	public StardictFileCreator(Dictionary dic) {
		this.dic = dic;
	}
	
	public void createStarDictFiles() {
		StardictFile dictFile;
		try {
			dictFile = new StardictFile(
					new DataOutputStream(new FileOutputStream("./data/enfi.ifo")),
					new DataOutputStream(new FileOutputStream("./data/enfi.idx")),
					new DataOutputStream(new FileOutputStream("./data/enfi.dict")),
					"English Finnish dictionary", "created by Tobias Domhan based on the english Wiktionary",
					"Tobias Domhan", "tdomhan.de", "tdomhan@gmail.com");
			Iterator<Translation> translations = dic.getFirstLangTranslations().iterator();
			createDictionary(translations, Translation.TranslationDirection.FIRST_SECOND_LANGUAGE, dictFile);
			
			dictFile = new StardictFile(
					new DataOutputStream(new FileOutputStream("./data/fien.ifo")),
					new DataOutputStream(new FileOutputStream("./data/fien.idx")),
					new DataOutputStream(new FileOutputStream("./data/fien.dict")),
					"Finnish English dictionary", "created by Tobias Domhan based on the english Wiktionary",
					"Tobias Domhan", "tdomhan.de", "tdomhan@gmail.com");
			translations = dic.getSecondLangTranslations().iterator();

			createDictionary(translations, Translation.TranslationDirection.SECOND_FIRST_LANGUAGE, dictFile);
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	private void createDictionary(Iterator<Translation> translations, Translation.TranslationDirection direction, StardictFile dictFile) throws IOException {
		StringBuilder currentEntry = new StringBuilder();
		int subentryCounter = 1;
		boolean newWord = true;
		boolean newType = false;
		boolean newMeaning = false;
		
		Translation.setTranslationDirection(direction);
		
		Translation prevTranslation = null;
		while(translations.hasNext()) {
			Translation nextTranslation = translations.next();
			if(prevTranslation != null) {
				if(!prevTranslation.getSourceLanguage().equals(nextTranslation.getSourceLanguage())) {
					newWord = true;
					newType = false;
					newMeaning = false;
					//append the last meaning
					addMeaning(currentEntry, prevTranslation.getMeaning());
					//now the entry can be written:
					dictFile.writeEntry(prevTranslation.getSourceLanguage(), currentEntry.toString());
					
					//start building a new entry
					currentEntry = new StringBuilder();
				} else if(!prevTranslation.getType().equals(nextTranslation.getType())) {
					newType = true;
					newMeaning = false;
				} else if(!prevTranslation.getMeaning().equals(nextTranslation.getMeaning())) {
					newMeaning = true;
				} else {
					newWord = false;
					newType = false;
					newMeaning = false;
				}
			}
			
			if(newWord) {
				subentryCounter = 1;
				currentEntry.append("\n");
				currentEntry.append(nextTranslation.getType().toString().toLowerCase());
				currentEntry.append(":\n");
				addSection(currentEntry, subentryCounter);
				addSubEntry(currentEntry, nextTranslation.getDestinationLanguage());
				newWord = false;
				newType = false;
				newMeaning = false;
			} else if(newType) {
				addMeaning(currentEntry, prevTranslation.getMeaning());
				subentryCounter = 1;
				currentEntry.append("\n");
				currentEntry.append(nextTranslation.getType().toString().toLowerCase());
				currentEntry.append(":\n");
				addSection(currentEntry, subentryCounter);
				addSubEntry(currentEntry, nextTranslation.getDestinationLanguage());
				newType = false;
				newMeaning = false;
			} else if(newMeaning) {
				addMeaning(currentEntry, prevTranslation.getMeaning());
				subentryCounter++;
				addSection(currentEntry, subentryCounter);
				addSubEntry(currentEntry, nextTranslation.getDestinationLanguage());
				newMeaning=false;
			} else {
				addSubEntry(currentEntry, nextTranslation.getDestinationLanguage());
			}
			
			prevTranslation = nextTranslation;
		}
		
		//append the last meaning
		addMeaning(currentEntry, prevTranslation.getMeaning());
		//now the entry can be written:
		dictFile.writeEntry(prevTranslation.getSourceLanguage(), currentEntry.toString());
		
		dictFile.writeInfo();
		dictFile.finish();
	}
	
	private void addMeaning(StringBuilder currentEntry, String meaning) {
		currentEntry.delete(currentEntry.length()-2, currentEntry.length());
		if(!meaning.isEmpty()) {
			currentEntry.append(" (");
			currentEntry.append(meaning);
			currentEntry.append(")\n");
		} else {
			currentEntry.append("\n");
		}
	}
	
	private void addSubEntry(StringBuilder currentEntry, String subentry) {
		currentEntry.append(subentry);
		currentEntry.append(", ");
	}
	
	private void addSection(StringBuilder currentEntry, int section) {
		currentEntry.append("  ");
		currentEntry.append(String.valueOf(section));
		currentEntry.append(". ");
	}
	
	public static void main(String[] args) throws IOException {
		//tmp test the StardictFile class:
		StardictFile dict = new StardictFile(
				new DataOutputStream(new FileOutputStream("./data/enfi.ifo")),
				new DataOutputStream(new FileOutputStream("./data/enfi.idx")),
				new DataOutputStream(new FileOutputStream("./data/enfi.dict")),
				"English Finnish dictionary", "created by Tobias Domhan based on the english Wiktionary",
				"Tobias Domhan", "tdomhan.de", "tdomhan@gmail.com");
		dict.writeEntry("aaa", "Definition of abc");
		dict.writeEntry("abc", "Verb\n  1. word1\n  2. word2\nNoun");
		dict.writeEntry("def", "Definition of def");
		dict.writeEntry("ghb", "Definition of ghb");
		dict.writeInfo();
		dict.finish();
	}
}
